package Activemq;

import Redis.Rdo;

import java.util.*;

public class RegionManager {
    private final int mapWidth;
    private final int mapHeight;
    private final Set<String> illuminatedCells; // 已照亮的单元格
    private final Map<String, String> carRegions; // 小车ID -> 区域key
    private final Map<String, Integer> regionCarCount; // 区域key -> 该区域的小车数量
    private final Map<String, Region> regions; // 区域key -> 区域对象（包含坐标范围）

    // 区域类，存储每个区域的坐标边界
    private static class Region {
        final int startX;
        final int endX;
        final int startY;
        final int endY;

        Region(int startX, int endX, int startY, int endY) {
            this.startX = startX;
            this.endX = endX;
            this.startY = startY;
            this.endY = endY;
        }
    }

    public RegionManager(int mapWidth, int mapHeight) {
        this.mapWidth = mapWidth;
        this.mapHeight = mapHeight;
        this.illuminatedCells = new HashSet<>();
        this.carRegions = new HashMap<>();
        this.regionCarCount = new HashMap<>();
        this.regions = new HashMap<>();
        initializeRegions();
    }

    // 动态分区初始化
    private void initializeRegions() {
        int regionCountX = calculateRegionCount(mapWidth); // X方向区域数
        int regionCountY = calculateRegionCount(mapHeight); // Y方向区域数

        // 计算每个区域的大小（最后一个区域可能更大）
        int regionWidth = (int) Math.ceil((double) mapWidth / regionCountX);
        int regionHeight = (int) Math.ceil((double) mapHeight / regionCountY);

        for (int row = 0; row < regionCountY; row++) {
            for (int col = 0; col < regionCountX; col++) {
                // 计算区域边界
                int startX = col * regionWidth;
                int endX = (col == regionCountX - 1) ? mapWidth : (col + 1) * regionWidth;
                int startY = row * regionHeight;
                int endY = (row == regionCountY - 1) ? mapHeight : (row + 1) * regionHeight;

                String regionKey = row + "," + col;
                regions.put(regionKey, new Region(startX, endX, startY, endY));
            }
        }
    }

    // 计算区域数量（动态调整）
    private int calculateRegionCount(int dimension) {
        if (dimension <= 10) return 1;
        if (dimension <= 20) return 2;
        if (dimension <= 50) return 3;
        return 4;
    }

    // 获取坐标所属的区域key
    public String getRegionKey(int x, int y) {
        for (Map.Entry<String, Region> entry : regions.entrySet()) {
            Region region = entry.getValue();
            if (x >= region.startX && x < region.endX &&
                    y >= region.startY && y < region.endY) {
                return entry.getKey();
            }
        }
        return "0,0"; // 默认返回第一个区域
    }

    // 标记单元格为已照亮
    public void markCellIlluminated(int x, int y) {
        illuminatedCells.add(x + "," + y);
    }

    // 分配车辆到区域
    public void assignCarToRegion(String carId, int x, int y) {
        String regionKey = getRegionKey(x, y);

        // 更新旧区域车辆计数
        String oldRegion = carRegions.get(carId);
        if (oldRegion != null) {
            regionCarCount.put(oldRegion, regionCarCount.getOrDefault(oldRegion, 1) - 1);
        }

        // 更新新区域
        carRegions.put(carId, regionKey);
        regionCarCount.put(regionKey, regionCarCount.getOrDefault(regionKey, 0) + 1);
    }

    // 优化目标选择策略
    public int[] findOptimalTarget(int startX, int startY, String carId, Rdo rdo) {
        String currentRegion = carRegions.get(carId);

        // 策略1：在当前区域查找
        if (currentRegion != null) {
            int[] target = findClosestInRegion(startX, startY, currentRegion, rdo);
            if (target != null) return target;
        }

        // 策略2：全局查找最近未照亮区域
        int[] globalTarget = findClosestUnexploredGlobally(startX, startY, rdo);
        if (globalTarget != null) return globalTarget;

        // 策略3：全图扫描保底
        return fullMapScan(startX, startY, rdo);
    }

    // 在当前区域查找最近未照亮点
    private int[] findClosestInRegion(int startX, int startY, String regionKey, Rdo rdo) {
        Region region = regions.get(regionKey);
        if (region == null) return null;

        int minDist = Integer.MAX_VALUE;
        int[] bestTarget = null;

        for (int x = region.startX; x < region.endX; x++) {
            for (int y = region.startY; y < region.endY; y++) {
                if (!rdo.checklight(x, y)) {
                    int dist = Math.abs(x - startX) + Math.abs(y - startY);
                    if (dist < minDist) {
                        minDist = dist;
                        bestTarget = new int[]{x, y};
                    }
                }
            }
        }
        return bestTarget;
    }

    // 全局查找最近未照亮区域
    // 优化后的策略2：全局查找（考虑区域负载）
    private int[] findClosestUnexploredGlobally(int startX, int startY, Rdo rdo) {
        double minScore = Double.MAX_VALUE;
        int[] bestTarget = null;

        for (String regionKey : regions.keySet()) {
            int[] target = findClosestInRegion(startX, startY, regionKey, rdo);
            if (target != null) {
                // 计算综合评分 = 距离 + 区域负载权重
                int dist = Math.abs(target[0] - startX) + Math.abs(target[1] - startY);
                int carCount = regionCarCount.getOrDefault(regionKey, 0);
                double score = dist * (1 + 0.5 * carCount); // 负载权重系数

                if (score < minScore) {
                    minScore = score;
                    bestTarget = target;
                }
            }
        }
        return bestTarget;
    }

    // 全图扫描（保底策略）
    private int[] fullMapScan(int startX, int startY, Rdo rdo) {
        int minDist = Integer.MAX_VALUE;
        int[] bestTarget = null;

        for (int x = 0; x < mapWidth; x++) {
            for (int y = 0; y < mapHeight; y++) {
                if (!rdo.checklight(x, y)) {
                    int dist = Math.abs(x - startX) + Math.abs(y - startY);
                    if (dist < minDist) {
                        minDist = dist;
                        bestTarget = new int[]{x, y};
                    }
                }
            }
        }
        return bestTarget;
    }
}